# -*- mode: python; coding: utf-8; -*-
##--------------------------------------------------------------------------##
##
## Copyright (C) 1998-2003 Markus Oberhumer <markus@oberhumer.com>
## Copyright (C) 2003 Mt. Hood Playing Card Co.
## Copyright (C) 2005-2010 Skomoroh <skomoroh@users.sourceforge.net>
## Copyright (C) 2010-2013 Jeremy Austin-Bardo <tjaustinbardo@gmail.com>
##
## This program is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program.  If not, see <http://www.gnu.org/licenses/>.
##
##--------------------------------------------------------------------------##
__docformat__ = 'restructuredtext en'

from ... import formlib as layout
from ... import pilelib as stack
from ...gamelib import info as gi, state, game
from ...packlib import info as cs, place
from ...piles import hexadeck as xstack

GT, SL = gi.GT, gi.SL
Wrap = stack.StackWrapper


class BitsNBytes(cs.HexA_Deck, game.Game):
    """
    Arrange cards by rank and least significant bit on rows to fill each.

    Layout
      - row [24 over 4 rows, no offset]
      - talon [W, no offset]
      - waste [1 S talon, no offset]
      - foundation [4 vert E talon, no offset]

    :CVariables:
      _talon_ : pysollib.stack.Stack
        .. pysollib.stack.WasteTalon (num_deal=2, max_rounds=2)

        Deal 2 card per `s.waste` on click. 1 redeal.

      _waste_ : pysollib.stack.Stack
        .. pysollib.stack.WasteStack

        Init 2 card. Build none. Play top.

      _foundation_ : pysollib.stack.Stack
        .. pysollib.stack.SS_Foundation (max_move=0, max_cards=1)

        Init 1 card per. Build none. Play none.

      _row_ : pysollib.stack.Stack
        .. pysollib.stacks.hexadeck.Bits_RowStack (max_move=0),
          pysollib.stacks.hexadeck.Bytes_RowStack (max_move=0)

        E 4:: Build in rank by least significant bit of row foundation and col
          when E has card. Play none.

        W 2:: Build by same rank when E has card. Play none.

      _hint_ : pysollib.hint.AbstractHint
        .. pysollib.hint.defaultHint
    """
    __info__ = dict(id=0x22385, name='Bits n Bytes',
                    category=cs.TYPE_HEXADECK, game_type=GT.ONE_DECK, decks=1,
                    redeals=1, version='4.20', skill_level=SL.BALANCED)
    __author__ = 'Markus Oberhumer'
    __version__ = 7.70

    _talon_ = Wrap(stack.WasteTalon, num_deal=2, max_rounds=2)
    _waste_ = stack.WasteStack
    _foundation_ = Wrap(stack.SS_Foundation, max_move=0, max_cards=1)
    _rows_ = (Wrap(xstack.Bits_RowStack, max_move=0),
              Wrap(xstack.Bytes_RowStack, max_move=0),)

    def _create_game(self):
        l, s = layout.layout(self, trump=False), self.s
        self.table_size = (4 * l.XM + 8 * l.XS, l.YM + l.YS * 4)
        y = l.YM
        dx = self.width - l.XS
        for j in l.SUIT:
            x = dx
            for i in range(4):
                s.rows['append'](self._rows_[0](x, y, game=self, base_suit=j))
                l.set_misc_text(s['rows'][-1], anchor='center')
                x -= l.XS
            y += l.YS
        y = l.YM
        dx -= 4 * l.XS
        for j in l.SUIT:
            x = dx
            for i in range(2):
                s.rows['append'](self._rows_[1](x, y, game=self))
                x -= l.XS
            y += l.YS
        dx -= 2 * l.XS
        y = l.YM
        for i in l.SUIT:
            s['foundations'].append(self._foundation_(x, y, game=self,
                                                      suit=i))
            y += l.YS
        self._set_region(s['rows'], l._region())
        x, y = l.XM, l.YM
        s['talon'] = self._talon_(x, y, game=self)
        l.set_ncards_text(s['talon'], 's')
        y += l.YS + l.TEXT_HEIGHT
        s['wastes'].append(self._waste_(x, y, game=self))
        l.set_ncards_text(s['wastes'][-1], 's')
        l.defaultStackGroups()
        return l

    @state.not_state('is_preview')
    def _update_text(self):
        """
        _update_text() -> None

        Set all `s.rowstacks` with bit stacks its bit text label.

        TODO: Move to pile method
        """
        foundations = self.s['foundations']
        for idx, pile in ((i, f) for i, f in enumerate(foundations) if f.cards):
            rank = pile.TOPCARD['rank'] + 1
            for j in range(4):
                stack = self.s['rows'][j + idx * 4]
                stack.texts['misc'].config(text=str(rank % 2))
                rank /= 2

    def _pile_place(self, cards):
        """
        _pile_place(cards) -> tuple

        Get a new copy of cards and shuffle. Place any non trump of each suit
        on top.

        :returns: deck of cards shuffle and placed.
        :seealso: `game.shuffle` for keyword details.
        """
        return place.MoveToTop(cards, lambda c: place.move(c,
                                                           suits=self['suits']))

    def _start(self):
        self._play_sound('deal')
        self.s['talon'].dealBaseCards(ncards=len(self.s['foundations']))
        self.s['talon'].deal_cards()

    @property
    def is_complete(self):
        """
        Check all `s.rowstacks` have a card.
        """
        return all(s.cards for s in self.s['rows'])


PROVIDES = [BitsNBytes]